package simpledb.execution;

import simpledb.storage.Field;
import simpledb.storage.Tuple;

import java.io.Serializable;

/**
 * Predicate 类表示对 Tuple 的 Field 的比较条件
 * 主要用于过滤符合条件的 Tuple，类似于 SQL 中的 WHERE 条件
 */
public class Predicate implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 操作符枚举，定义了所有支持的比较运算。
     * 持的操作包括：等于、大于、小于、LIKE 等。
     */
    public enum Op implements Serializable {
        EQUALS, GREATER_THAN, LESS_THAN, LESS_THAN_OR_EQ, GREATER_THAN_OR_EQ, LIKE, NOT_EQUALS;

        /**
         * 根据整数索引获取对应的 Op 操作符
         * 命令行工具中可以通过数字传参更方便地来指定操作符
         * @param i     枚举数组的下标 0~6
         * @return      对应的操作符
         */
        public static Op getOp(int i) {
            return values()[i];
        }

        /**
         * 返回该操作符的字符串表示形式。
         */
        public String toString() {
            if (this == EQUALS)
                return "=";
            if (this == GREATER_THAN)
                return ">";
            if (this == LESS_THAN)
                return "<";
            if (this == LESS_THAN_OR_EQ)
                return "<=";
            if (this == GREATER_THAN_OR_EQ)
                return ">=";
            if (this == LIKE)
                return "LIKE";
            if (this == NOT_EQUALS)
                return "<>";
            throw new IllegalStateException("不可能到达这里");
        }
    }

    // Predicate 的成员变量

    // 要比较的字段在 Tuple 中的位置（列号）
    private int   field;

    // 比较操作符
    private Op    op;

    // 要比较的目标值（Field 类型）
    private Field operand;

    /**
     * 构造函数
     *
     * @param field 字段在元组中的位置（从 0 开始计数）
     * @param op 比较操作符（如 >, <, = 等）
     * @param operand 要比较的目标字段值
     */
    public Predicate(int field, Op op, Field operand) {
        this.field = field;
        this.op = op;
        this.operand = operand;
    }

    /**
     * 获取当前比较所针对的字段编号
     *
     * @return 字段编号
     */
    public int getField() {
        return this.field;
    }

    /**
     * 获取当前使用的比较操作符
     *
     * @return 操作符（Op 类型）
     */
    public Op getOp() {
        return this.op;
    }

    /**
     * 获取比较的目标字段值
     *
     * @return 目标字段值（Field 类型）
     */
    public Field getOperand() {
        return this.operand;
    }

    /**
     * 判断给定的元组是否满足当前的谓词条件。
     * 实际上是调用了 Field.compare 方法进行比较。
     *
     * @param t 要判断的元组
     * @return 如果满足条件返回 true，否则返回 false
     */
    public boolean filter(Tuple t) {
        final Field field1 = t.getField(this.field); // 获取元组中指定字段的值
        final Field field2 = this.operand; // 获取比较的目标值
        return field1.compare(this.op, field2); // 执行比较
    }

    /**
     * 返回谓词的字符串表示，便于调试输出。
     */
    @Override
    public String toString() {
        return "Predicate{" + "field=" + field + ", op=" + op + ", operand=" + operand + '}';
    }
}
